package CalendarComponents;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import Managers.Appointment;
import Managers.CalendarManager;
import Managers.Category;
import Managers.CategoryManager;
import Managers.Day;
import Managers.Repeat;
import CalendarComponents.Reminder;

import calendar.MainWindow;

import com.toedter.calendar.JDateChooser;

/**
 * Class representing the main dialog for creating or altering and appointment. The dialog is modal and when closed, just disposes but does not close the application itself.
 * @author Christian G.
 * 
 * This class uses the 3rd party "JDateChooser"-class from the "JCalendar" library (http://www.toedter.com/en/jcalendar/index.html)
 **/
@SuppressWarnings("serial")
public class PropertiesDialog extends JDialog{

	private String[] times = new String[]{"07:00","07:30","08:00","08:30","09:00","09:30","10:00","10:30","11:00","11:30","12:00","12:30","13:00","13:30","14:00","14:30","15:00","15:30","16:00","16:30","17:00","17:30","18:00","18:30","19:00","19:30","20:00","20:30","21:00","21:30","22:00","22:30","23:00","23:30"};
	private String[] reminderLengthsHours = new String[]{"1","2","3","4","5","6","7","8","9","10","11"};
	private String[] reminderLengthsMinutes = new String[]{"5","10","15","20","25","30","35","40","45","50","55"};
	private String[] reminderLengthsDays= new String[]{"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31"};
	private String[] reminderUnits = new String[]{Reminder.UNIT_MINUTES,Reminder.UNIT_HOURS,Reminder.UNIT_DAYS};
	private String[] reminderTypes = new String[]{Reminder.TYPE_E_MAIL, Reminder.TYPE_POP_UP};
	//Yet for 12 weeks = 3 months
	private String[] repeatIntervalsWeeks = new String[]{"1","2","3","4","5","6","7","8","9","10","11","12"};
	private String[] repeatIntervals = new String[]{"Weekly","Daily","Monthly","Yearly"};
	//Day object from CalendarManager, specifying time intervals and the current day
	private Day day = CalendarManager.getDay();
	private Date date;
	//Internally stored Appointment object. This is generated when "Confirm" is hit and erased again when the dialog is made visible the next time. 
	private Appointment appointment;
	private Appointment old_appointment;
	
	private JDialog dialogFrame;
	
	private JTextField tfAppointmentTitle;
	private JPanel startEndPanel;
	private JDateChooser dcBegin;
	private JDateChooser dcEnd; 
	private JLabel lAllDayAppointment;
	private JCheckBox chbAllDayAppointment;
	private JComboBox cbTimeStart;
	private JComboBox cbTimeEnd;
	private JLabel lCategory;
	private JButton bCustomCat;
	private JComboBox cbCategory;
	private JButton	bMoreOptions;
	private JButton bDeleteAppointment;
	private JButton bConfirm;
	private JButton bCancel;
	
	private JPanel expansionPanel;
	private JLabel lWhere;
	private JTextField tfWhere;
	private JLabel lDescription;
	private JTextArea taDescription;
	private JLabel lRepeat;
	private JCheckBox chbRepeat;
	private JPanel repeatPanel;
	private JLabel lReminder;
	private JCheckBox chbReminder;
	private JPanel reminderPanel;
	
	private JLabel lRepeatInterval;
	private JComboBox cbRepeatInterval;
	private JLabel lRepeatEvery;
	private JComboBox cbRepeatWeeks;
	private JLabel lRepeatWeeks;
	private JLabel lRepeatOn;
	private JPanel weekdayPanel;
	private JLabel lStartsOn;
	private JLabel lStartsOnDate;
	private JLabel lEndsOn;
	private JRadioButton rbNever;
	private JRadioButton rbUntil;
	private JDateChooser tfDateUntil;
	
	private JCheckBox chbMonday;
	private JCheckBox chbTuesday;
	private JCheckBox chbWednesday;
	private JCheckBox chbThursday;
	private JCheckBox chbFriday;
	private JCheckBox chbSaturday;
	private JCheckBox chbSunday;
	
	private JComboBox cbReminderType;
	private JComboBox cbReminderLength;
	private JComboBox cbReminderUnits;
	private JButton bAddReminder;
	private JPanel reminderItemsPanel;
	private JScrollPane reminderItemsSP;
	
	private static String CUSTOM_CATEGORY_CMD="custom category";
	private static String MORE_OPTIONS_CMD="more options";
	private static String DELETE_APPOINTMENT_CMD="delete app";
	private static String CONFIRM_CMD="confirm";
	private static String CANCEL_CMD="cancel";
	private static String RB_NEVER_CMD = "never";
	private static String RB_UNTIL_CMD = "until";
	private static String ADD_REMINDER_CMD = "add reminder";
	private static String REMINDER_UNITS_CMD = "reminder units changed";
	
	private AHandler aHandler = new AHandler();
	private IHandler iHandler = new IHandler();
	
	/**
	 * Constructor, needs the parent JFrame to align the dialog accordingly
	 * @param parent the parent JFrame
	 * @param start 
	 */
	public PropertiesDialog(JFrame parent, Day start){
		//Create a modal (true) dialog aligned according to the given JFrame with the title "Properties"
		super(parent, "Create/Alter Appointment", true);
	    if (parent != null) {
	        Dimension parentSize = parent.getSize(); 
	        Point p = parent.getLocation(); 
	        setLocation(p.x + parentSize.width / 4, p.y + parentSize.height / 4);
	    }
	    //Just dispose, not exit the program!
	    this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
	    //Do not resize!
	    this.setResizable(false);
	    
	    this.dialogFrame=this;
	    
		//Get the current date
	    
		this.setDay(start);
		Date date = new Date();
		date.setDate(this.getDay().getDate()[0]); //day
		date.setMonth(this.getDay().getDate()[1]); //month
		date.setYear(this.getDay().getDate()[2]-1900); //year
		this.setDate(date);
	    
	    this.createDialog();
	    //Deactivate the advanced options by default
	    this.expansionPanel.setVisible(false);
	    this.enablePanel(false, reminderPanel);
	    this.enablePanel(false, repeatPanel);
	    this.enablePanel(false, reminderItemsPanel);
	    
	    pack();
	}
	
	/**
	 * Constructor which instantly applies a given appointment to the dialog
	 * @param parent the parent JFrame
	 * @param a a given object of type Appointment
	 */
	public PropertiesDialog(JFrame parent, Appointment a){
		this(parent, a==null?CalendarManager.getDay():CalendarManager.getDay(a.getStart()));
		this.setAppointment(a);
		this.setOldAppointment(a);
		this.bDeleteAppointment.setEnabled(true);
	    //If there's no appointment assigned yet, disable the delete-button
	    if(a==null){
	    	this.bDeleteAppointment.setEnabled(false);
	    }
	}
	
	/**
	 * Method to create the components of the Dialog
	 */
	private void createDialog(){
		
		//Use a GridBagLayout and divide the Panel in 4 columns for each row
		this.setLayout(new GridBagLayout());
		
		tfAppointmentTitle = new JTextField("Title of Appointment");
		GridBagConstraints tfAppointmentTitleGbc = this.createConstraints(0, 0, 2, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		this.add(tfAppointmentTitle, tfAppointmentTitleGbc);
		
		startEndPanel = new JPanel();
		startEndPanel.setBorder(BorderFactory.createTitledBorder("Start/end date/time"));
		GridBagConstraints startEndPanelGbc = this.createConstraints(2, 0, 2, 3, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,0,0,0));
		GridLayout gl = new GridLayout(3,2);
		gl.setHgap(5);
		gl.setVgap(5);
		startEndPanel.setLayout(gl);
		this.add(startEndPanel, startEndPanelGbc);
		
		dcBegin = new JDateChooser(this.getDate());
		dcBegin.setToolTipText("Starting date of appointment");
		dcBegin.setDateFormatString("dd/MM/yyyy");
		dcBegin.setPreferredSize(new Dimension(130,20));
		startEndPanel.add(dcBegin);
		
		cbTimeStart = new JComboBox(times);
		cbTimeStart.setToolTipText("Starting time of appointment");
		startEndPanel.add(cbTimeStart);
	
		dcEnd = new JDateChooser(this.getDate());
		dcEnd.setToolTipText("Ending date of appointment");
		dcEnd.setDateFormatString("dd/MM/yyyy");
		dcEnd.setPreferredSize(new Dimension(130,20));
		startEndPanel.add(dcEnd);
	
		cbTimeEnd = new JComboBox(times);
		cbTimeEnd.setToolTipText("Ending time of appointment");
		startEndPanel.add(cbTimeEnd);
		
		lAllDayAppointment = new JLabel("All-Day-Appointment:");
		lAllDayAppointment.setPreferredSize(new Dimension(120,30));
		startEndPanel.add(lAllDayAppointment);
		
		chbAllDayAppointment = new JCheckBox();
		chbAllDayAppointment.addItemListener(iHandler);
		startEndPanel.add(chbAllDayAppointment);
		
		lCategory = new JLabel("Category:");
		GridBagConstraints lCategoryGbc = this.createConstraints(0, 1, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		this.add(lCategory, lCategoryGbc);
		
		//Customizable ComboBox, displaying labels with a color (=categories)
		Category[] categories = CategoryManager.getList();
		CategoryRenderer renderer = new CategoryRenderer();
		cbCategory = new JComboBox(categories);
		cbCategory.setRenderer(renderer);
		GridBagConstraints cbCategoryGbc = this.createConstraints(1, 1, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		this.add(cbCategory, cbCategoryGbc);
		
		bCustomCat = new JButton("Custom Category");
		bCustomCat.setActionCommand(CUSTOM_CATEGORY_CMD);
		bCustomCat.addActionListener(aHandler);
		bCustomCat.setToolTipText("Create a custom category");
		GridBagConstraints bCustomCatGbc = this.createConstraints(1, 2, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		this.add(bCustomCat, bCustomCatGbc);
		
		bMoreOptions = new JButton("More Options");
		bMoreOptions.setToolTipText("Add Place, Description, Repetitions and Reminders");
		bMoreOptions.setActionCommand(MORE_OPTIONS_CMD);
		bMoreOptions.addActionListener(aHandler);
		GridBagConstraints bMoreOptionsGbc = this.createConstraints(0, 3, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		this.add(bMoreOptions, bMoreOptionsGbc);
		
		bDeleteAppointment = new JButton("Delete Appointment");
		bDeleteAppointment.setActionCommand(DELETE_APPOINTMENT_CMD);
		bDeleteAppointment.setEnabled(false);
		bDeleteAppointment.addActionListener(aHandler);
		bDeleteAppointment.setToolTipText("Delete this appointment from the calendar");
		GridBagConstraints bDeleteAppointmentGbc = this.createConstraints(1, 3, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		this.add(bDeleteAppointment, bDeleteAppointmentGbc);
		
		bConfirm = new JButton("Confirm");
		bConfirm.setActionCommand(CONFIRM_CMD);
		bConfirm.addActionListener(aHandler);
		bConfirm.setToolTipText("Save the appointment and close this dialog");
		GridBagConstraints bConfirmGbc = this.createConstraints(2, 3, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		this.add(bConfirm, bConfirmGbc);
		
		bCancel = new JButton("Cancel");
		bCancel.setActionCommand(CANCEL_CMD);
		bCancel.addActionListener(aHandler);
		bConfirm.setToolTipText("Discard changes and close this dialog");
		GridBagConstraints bCancelGbc = this.createConstraints(3, 3, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		this.add(bCancel, bCancelGbc);
		
		//Call the subroutine to create the expansion panel
		expansionPanel = this.createExpansionPanel();
		GridBagConstraints expansionPanelGbc = this.createConstraints(0, 4, 4, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,0,0,0));
		this.add(expansionPanel, expansionPanelGbc);
		
	}
	
	private JPanel createExpansionPanel(){
		
		//Create subpanel, displaying the expandable content
		expansionPanel = new JPanel();
		expansionPanel.setBorder(BorderFactory.createTitledBorder("More options"));
		expansionPanel.setLayout(new GridBagLayout());

		lWhere = new JLabel("Where:");
		lWhere.setPreferredSize(new Dimension(135,30));
		GridBagConstraints lWhereGbc = this.createConstraints(0, 0, 2, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		expansionPanel.add(lWhere, lWhereGbc);
		
		tfWhere = new JTextField();
		GridBagConstraints tfWhereGbc = this.createConstraints(2, 0, 2, 1, 4, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,0,5,5));
		expansionPanel.add(tfWhere, tfWhereGbc);
		
		lDescription = new JLabel("Description:");
		GridBagConstraints lDescriptionGbc = this.createConstraints(0, 1, 2, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		expansionPanel.add(lDescription, lDescriptionGbc);
		
		taDescription = new JTextArea();
		JScrollPane spDescription = new JScrollPane(taDescription);
		spDescription.setPreferredSize(new Dimension(300,100));
		taDescription.setLineWrap(true);
		GridBagConstraints spDescriptionGbc = this.createConstraints(2, 1, 2, 2, 4, 1, GridBagConstraints.BOTH, GridBagConstraints.FIRST_LINE_START, new Insets(5,0,5,5));
		expansionPanel.add(spDescription, spDescriptionGbc);
		
		lRepeat = new JLabel("Repeat: ");
		GridBagConstraints lRepeatGbc = this.createConstraints(0, 4, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		expansionPanel.add(lRepeat, lRepeatGbc);
		
		chbRepeat = new JCheckBox();
		chbRepeat.addItemListener(iHandler);
		GridBagConstraints chbRepeatGbc = this.createConstraints(1, 4, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		expansionPanel.add(chbRepeat, chbRepeatGbc);
		
		//Call the subroutine to create the repeat settings panel
		repeatPanel = this.createRepeatPanel();
		GridBagConstraints repeatPanelGbc = this.createConstraints(2, 4, 2, 1, 1, 1, GridBagConstraints.BOTH, GridBagConstraints.FIRST_LINE_START, new Insets(0,0,0,0));
		expansionPanel.add(repeatPanel, repeatPanelGbc);
		
		lReminder = new JLabel("Reminder: ");
		GridBagConstraints lReminderGbc = this.createConstraints(0, 5, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		expansionPanel.add(lReminder, lReminderGbc);
		
		chbReminder = new JCheckBox();
		chbReminder.addItemListener(iHandler);
		GridBagConstraints chbReminderGbc = this.createConstraints(1, 5, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(5,5,5,5));
		expansionPanel.add(chbReminder, chbReminderGbc);
		
		//Panel for the repeat-controls. Should enabled according to the checkbox
		reminderPanel = this.createReminderPanel();
		GridBagConstraints reminderPanelGbc = this.createConstraints(2, 5, 2, 1, 1, 1, GridBagConstraints.BOTH, GridBagConstraints.FIRST_LINE_START, new Insets(0,0,0,0));
		expansionPanel.add(reminderPanel, reminderPanelGbc);
		
		return expansionPanel;
	}
	
	private JPanel createRepeatPanel(){
		
		//Panel for the repeat-controls. Should enabled according to the checkbox
		repeatPanel = new JPanel();
		repeatPanel.setBorder(BorderFactory.createTitledBorder("Repeat Settings"));
		repeatPanel.setLayout(new GridBagLayout());
		
		lRepeatInterval = new JLabel("Repeats: ");
		GridBagConstraints lRepeatIntervalGbc = this.createConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		repeatPanel.add(lRepeatInterval, lRepeatIntervalGbc);
		
		cbRepeatInterval = new JComboBox(repeatIntervals);
		GridBagConstraints cbRepeatIntervalGbc = this.createConstraints(1, 0, 3, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		repeatPanel.add(cbRepeatInterval,cbRepeatIntervalGbc);
		
		lRepeatEvery = new JLabel("Repeat every: ");
		GridBagConstraints lRepeatEveryGbc = this.createConstraints(0, 1, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		repeatPanel.add(lRepeatEvery,lRepeatEveryGbc);
		
		cbRepeatWeeks = new JComboBox(repeatIntervalsWeeks);
		GridBagConstraints cbRepeatWeeksGbc = this.createConstraints(1, 1, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		repeatPanel.add(cbRepeatWeeks, cbRepeatWeeksGbc);
		
		lRepeatWeeks = new JLabel("weeks");
		GridBagConstraints lRepeatWeeksGbc = this.createConstraints(2, 1, 2, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		repeatPanel.add(lRepeatWeeks,lRepeatWeeksGbc);
		
		lRepeatOn = new JLabel("Repeat on:");
		GridBagConstraints lRepeatOnGbc = this.createConstraints(0, 2, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		repeatPanel.add(lRepeatOn, lRepeatOnGbc);
		
		weekdayPanel = this.createWeekdayPanel();
		GridBagConstraints weekdayPanelGbc = this.createConstraints(1, 2, 3, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		repeatPanel.add(weekdayPanel,weekdayPanelGbc);
		
		lStartsOn = new JLabel("Starts on:");
		GridBagConstraints lStartsOnGbc = this.createConstraints(0, 3, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		repeatPanel.add(lStartsOn,lStartsOnGbc);
		
		Date d = this.getDate();
		String dateString = d.getDate() + "/" + (d.getMonth()+1) + "/" + (d.getYear()+1900);
		lStartsOnDate = new JLabel(dateString);
		GridBagConstraints lStartsOnDateGbc = this.createConstraints(1, 3, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		repeatPanel.add(lStartsOnDate,lStartsOnDateGbc);
		
		lEndsOn = new JLabel("Ends on:");
		GridBagConstraints lEndsOnGbc = this.createConstraints(0, 4, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		repeatPanel.add(lEndsOn,lEndsOnGbc);
		
		rbNever = new JRadioButton("never");
		rbNever.setSelected(true);
		rbNever.addActionListener(aHandler);
		GridBagConstraints rbNeverGbc = this.createConstraints(1, 4, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		repeatPanel.add(rbNever, rbNeverGbc);
		
		rbUntil = new JRadioButton("until");
		rbUntil.addActionListener(aHandler);
		GridBagConstraints rbUntilGbc = this.createConstraints(2, 4, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		repeatPanel.add(rbUntil, rbUntilGbc);
		
		ButtonGroup endsOnGroup = new ButtonGroup();
		endsOnGroup.add(rbNever);
		endsOnGroup.add(rbUntil);
		
		tfDateUntil = new JDateChooser(date);
		tfDateUntil.setDateFormatString("dd/MM/yyyy");
		tfDateUntil.setPreferredSize(new Dimension(130,20));
		tfDateUntil.setEnabled(false);
		GridBagConstraints tfDateUntilGbc = this.createConstraints(3, 4, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		repeatPanel.add(tfDateUntil,tfDateUntilGbc);
		
		return repeatPanel;
	}
	
	private JPanel createWeekdayPanel(){
		
		weekdayPanel = new JPanel();
		weekdayPanel.setLayout(new GridLayout(0,7));
		
		chbMonday = new JCheckBox("M");
		weekdayPanel.add(chbMonday);
		
		chbTuesday = new JCheckBox("T");
		weekdayPanel.add(chbTuesday);
		
		chbWednesday = new JCheckBox("W");
		weekdayPanel.add(chbWednesday);
		
		chbThursday = new JCheckBox("T");
		weekdayPanel.add(chbThursday);
		
		chbFriday = new JCheckBox("F");
		weekdayPanel.add(chbFriday);
		
		chbSaturday = new JCheckBox("S");
		weekdayPanel.add(chbSaturday);
		
		chbSunday = new JCheckBox("S");
		weekdayPanel.add(chbSunday);
		
		return weekdayPanel;
	}

	private JPanel createReminderPanel(){
		
		reminderPanel = new JPanel();
		reminderPanel.setBorder(BorderFactory.createTitledBorder("Reminder Settings"));
		reminderPanel.setLayout(new GridBagLayout());
		
		cbReminderType = new JComboBox(reminderTypes);
		GridBagConstraints cbReminderTypeGbc = this.createConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		reminderPanel.add(cbReminderType,cbReminderTypeGbc);
		
		cbReminderLength = new JComboBox(reminderLengthsMinutes);
		GridBagConstraints cbReminderLengthGbc = this.createConstraints(1, 0, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		reminderPanel.add(cbReminderLength,cbReminderLengthGbc);
		
		cbReminderUnits = new JComboBox(reminderUnits);
		cbReminderUnits.setActionCommand(REMINDER_UNITS_CMD);
		cbReminderUnits.addActionListener(aHandler);
		GridBagConstraints cbReminderUnitsGbc = this.createConstraints(2, 0, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		reminderPanel.add(cbReminderUnits,cbReminderUnitsGbc);
		
		bAddReminder = new JButton("Add Reminder");
		bAddReminder.setActionCommand(ADD_REMINDER_CMD);
		bAddReminder.addActionListener(aHandler);
		GridBagConstraints bAddReminderGbc = this.createConstraints(2, 1, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		reminderPanel.add(bAddReminder,bAddReminderGbc);
		
		reminderItemsPanel = new JPanel();
		reminderItemsPanel.setLayout(new BoxLayout(reminderItemsPanel,BoxLayout.Y_AXIS));
		
		reminderItemsSP = new JScrollPane(reminderItemsPanel);
		reminderItemsSP.setPreferredSize(new Dimension(200,80));
		reminderItemsSP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		GridBagConstraints reminderItemsSPGbc = this.createConstraints(0, 2, 3, 2, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(5,5,5,5));
		reminderPanel.add(reminderItemsSP, reminderItemsSPGbc);
		
		return reminderPanel;
	}
	
	/**
	 * Method used to shorten the layout code, just outsources common GridBagLayout-constraints
	 * @return a Constraint Object for the GridBagLayout
	 **/
	private GridBagConstraints createConstraints(int x, int y, int width, int height, int weightX, int weightY, int fill, int anchor, Insets insets){
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.gridx = x;
		gbc.gridy = y;
		gbc.gridwidth = width;
		gbc.gridheight = height;
		gbc.weightx = weightX;
		gbc.weighty = weightY;
		gbc.fill = fill;
		gbc.insets = insets;
		gbc.anchor = anchor;
		
		return gbc;
	}
	
	/**
	 * Method used to recursively enable/disable all Components in a particular JPanel
	 */
	private void enablePanel(boolean enable, JPanel panel){
		for(int i=0; i<panel.getComponentCount(); i++){
			panel.getComponent(i).setEnabled(enable);
			if(panel.getComponent(i) instanceof JPanel){
				this.enablePanel(enable, (JPanel)panel.getComponent(i));
			}
		}
	}
	
	/**
	 * Remove a ReminderItem from the corresponding panel. This method is called by the item itself when hitting the delete button 
	 */
	public void removeReminderItem(ReminderItem i){
		this.reminderItemsPanel.remove(i);
		this.reminderItemsPanel.revalidate();
		this.reminderItemsPanel.repaint();
	}
	
	
	/*
	 * There is a problem with the way JDateChooser returns the calendar day
	 * soo i've having to rebuild the calendar including the hour and minutes
	 */
	
	private Calendar getStartTime()
	{
		Calendar c = dcBegin.getCalendar();
		
		int y = c.get(Calendar.YEAR);
		
		int m = c.get(Calendar.MONTH);
		
		int d = c.get(Calendar.DAY_OF_MONTH);
		
		String sT = (String)cbTimeStart.getSelectedItem();
		int[] times = new int[]{
				Integer.parseInt(sT.substring(0, 2)),
				Integer.parseInt(sT.substring(3, 5))
		};
		int h = times[0];
		
		int min = times[1];
		
		c.clear();
		
		c.set(y, m, d, h, min, 0);
		
		return c;
	}
	
	private Calendar getFinishTime()
	{
		Calendar c = dcEnd.getCalendar();
		
		int y = c.get(Calendar.YEAR);
		
		int m = c.get(Calendar.MONTH);
		
		int d = c.get(Calendar.DAY_OF_MONTH);
		
		String eT = (String)cbTimeStart.getSelectedItem();
		
		int[] times = new int[]{
				Integer.parseInt(eT.substring(0, 2)),
				Integer.parseInt(eT.substring(3, 5))
		};
		int h = times[0];
		
		int min = times[1];
		
		c.clear();
		
		c.set(y, m, d, h, min, 0);
		return c;
	}
	
	
	//CC Added these for easy retrieval
	/*
	public Appointment getAppointment()
	{
		Appointment a = new Appointment(
				tfAppointmentTitle.getText(),
				getStartTime(),
				getFinishTime(),//dcEnd.getCalendar(),
				taDescription.getText(),
				(Category)cbCategory.getSelectedItem()
				);
		return a;
	}*/
	
	//Nearly same method, other name
	public Appointment createAppointment()
	{
		Category c;
		if((Category)cbCategory.getSelectedItem() == null)
		{
			c = Category.None();
		}
		else
		{
			c = (Category)cbCategory.getSelectedItem();
		}
		Appointment a = new Appointment(
				tfAppointmentTitle.getText(),
				getStartTime(),
				getFinishTime(),//dcEnd.getCalendar(),
				taDescription.getText(),
				c
				);
		a.setPlace(tfWhere.getText());
		a.setReminders(this.getReminders());
		a.setRepeat(this.getRepeat());
		
		this.appointment = a;
		return a;
	}
	
	/*
	 * Used to provide the createAppointment method with the necessary information from the Components, encapsulated in a Repeat-Object
	 */
	private Repeat getRepeat(){
		
		if(chbRepeat.isSelected()){
			ArrayList<String> repeatOn = new ArrayList<String>();
		
			if(chbMonday.isSelected()){
				repeatOn.add("Monday");
			}
			if(chbTuesday.isSelected()){
				repeatOn.add("Tuesday");
			}
			if(chbWednesday.isSelected()){
				repeatOn.add("Wednesday");
			}
			if(chbThursday.isSelected()){
				repeatOn.add("Thursday");
			}
			if(chbFriday.isSelected()){
				repeatOn.add("Friday");
			}
			if(chbSaturday.isSelected()){
				repeatOn.add("Saturday");
			}
			if(chbSunday.isSelected()){
				repeatOn.add("Sunday");
			}
		
			Repeat r = new Repeat((String)cbRepeatInterval.getSelectedItem(), 
				(String)cbRepeatWeeks.getSelectedItem(), 
				repeatOn, 
				rbUntil.isSelected(), 
				tfDateUntil.getDate());
		
		return r;
		}
		return null;
		
	}
	
	/*
	 * Used to provide the createAppointment method with the necessary information from the Components, retrieving all Reminder-objects
	 */
	private ArrayList<Reminder> getReminders(){
		ArrayList<Reminder> r = new ArrayList<Reminder>();
		
		for(int i=0; i<reminderItemsPanel.getComponentCount(); i++){
			r.add(((ReminderItem)reminderItemsPanel.getComponent(i)).getReminder());
		}
		
		return r;
	}
	
	//Get an appointment when Confirm has been clicked before, else return null
	public Appointment getAppointment(){
		return appointment;
	}
	
	//CC Added these for easy setting
	public void setAppointment(Appointment a)
	{
		if(a!=null){
		tfAppointmentTitle.setText(a.getApointmentName());
		dcBegin.setCalendar(a.getStart());
		dcEnd.setCalendar(a.getFinish());
		taDescription.setText(a.getDescription());
		cbCategory.setSelectedItem(a.getCategory());
		tfWhere.setText(a.getPlace());
		
		//If repeat was set-up
		if(a.getRepeat()!=null){
			chbRepeat.setSelected(true);
			Repeat r = a.getRepeat();
			
			cbRepeatInterval.setSelectedItem(r.getRepeatUnit());
			cbRepeatWeeks.setSelectedItem(r.getRepeatEvery());
			rbUntil.setSelected(r.isEndsUntil());
			tfDateUntil.setDate(r.getRepeatUntil());
			
			ArrayList<String> repeatOn = r.getRepeatOn();
			for(int i=0; i<repeatOn.size(); i++){
				String temp = repeatOn.get(i);
				if(temp.equals("Monday")){
					chbMonday.setSelected(true);
				}else if(temp.equals("Tuesday")){
					chbTuesday.setSelected(true);
				}else if(temp.equals("Wednesday")){
					chbWednesday.setSelected(true);
				}else if(temp.equals("Thursday")){
					chbThursday.setSelected(true);
				}else if(temp.equals("Friday")){
					chbFriday.setSelected(true);
				}else if(temp.equals("Saturday")){
					chbSaturday.setSelected(true);
				}else if(temp.equals("Sunday")){
					chbSunday.setSelected(true);
				}
			}
		}
		
		if(a.getReminders().size()!=0){
			chbReminder.setSelected(true);
			reminderItemsPanel.removeAll();
			for(int i=0; i<a.getReminders().size(); i++){
				reminderItemsPanel.add(new ReminderItem(a.getReminders().get(i), (PropertiesDialog)dialogFrame));
			}
		}
		
		}
		
		
		this.appointment = a;
	}	
	
	private class AHandler implements ActionListener{

	    public void actionPerformed(ActionEvent arg0) {
			String cmd = arg0.getActionCommand();
			if(cmd.equals(MORE_OPTIONS_CMD)){
				if(expansionPanel.isVisible()){
					expansionPanel.setVisible(false);
					dialogFrame.pack();
				}else{
					expansionPanel.setVisible(true);
					dialogFrame.pack();
				}
			}else if(cmd.equals(DELETE_APPOINTMENT_CMD)){
				
				//Use the premade ConfirmDialog to ask for the users confirmation to delete the appointment
				int decision = JOptionPane.showConfirmDialog(
					    dialogFrame,
					    "Are you sure that you want to delete this appointment?",
					    "Really?",
					    JOptionPane.YES_NO_OPTION);
				
				if(decision==JOptionPane.YES_OPTION){
					getAppointment().setDeleted(true);
					dialogFrame.setVisible(false);
				}
			}else if(cmd.equals(CONFIRM_CMD)){
				
				if(!tfAppointmentTitle.getText().equals("Title of Appointment")){
					//Create the appointment (analogous to alter the given one)
					createAppointment();
					dialogFrame.setVisible(false);
				}else{
					//Notification dialog asking the user to enter another name than the default one, doing nothing
					JOptionPane.showMessageDialog(dialogFrame,
						    "Please enter a name for the appointment which is not the default one",
						    "No name given",
						    JOptionPane.WARNING_MESSAGE);
				}
				
			}else if(cmd.equals(CANCEL_CMD)){
				//Nothing should happen, just make the dialog disappear again
				setAppointment(null);
				dialogFrame.setVisible(false);
		    }else if(cmd.equals(RB_NEVER_CMD)){
		    	tfDateUntil.setEnabled(false);
		    }else if(cmd.equals(RB_UNTIL_CMD)){
		    	tfDateUntil.setEnabled(true);
		    }else if(cmd.equals(ADD_REMINDER_CMD)){
		    	String type = (String)cbReminderType.getSelectedItem();
		    	int length = Integer.parseInt((String)cbReminderLength.getSelectedItem());
		    	String units = (String)cbReminderUnits.getSelectedItem();
		    	Reminder r = new Reminder(type, units, length);
				reminderItemsPanel.add(new ReminderItem(r,(PropertiesDialog)dialogFrame));
				reminderItemsPanel.revalidate();
		    }else if(cmd.equals(REMINDER_UNITS_CMD)){
		        String unit = (String)cbReminderUnits.getSelectedItem();
		        String[] list = new String[0];
		        if(unit.equals("Minutes")){
		        	list=reminderLengthsMinutes;
		        }else if(unit.equals("Hours")){
		        	list=reminderLengthsHours;
		        }else if(unit.equals("Days")){
		        	list=reminderLengthsDays;
		        }
		        cbReminderLength.removeAllItems();
		        for(int i=0; i<list.length; i++){
	        		cbReminderLength.addItem(list[i]);
	        	}
	        	cbReminderLength.revalidate();
	        	cbReminderLength.repaint();
		    }else if(cmd.equals(CUSTOM_CATEGORY_CMD)){
		    	//Can't initialise this with the dialog as parent because JDialog doesn't inhibit from JFrame, so just giving null as argument
		    	//CC MainWindow Has a method for getting the current instance of MainWindow which you can use.
		    	CategoryDialog categoryDialog = new CategoryDialog(MainWindow.getMainWindow());
		    	categoryDialog.setVisible(true);
		    	//The dialog automatically adds new categories to the CategoryManager, so catch them from there
		    	Category[] cats = CategoryManager.getList();
		    	cbCategory.removeAllItems();
		    	for(int i=0; i<cats.length; i++){
		    		cbCategory.addItem(cats[i]);
		    	}
		    	cbCategory.revalidate();
		    	cbCategory.repaint();
		    	cbCategory.setSelectedIndex(cats.length-1);
		    }
		}
	}
	
	private class IHandler implements ItemListener{
		
		public void itemStateChanged(ItemEvent arg0) {
			Object source = arg0.getItemSelectable();
			if (source == chbRepeat) {
				//System.out.println("Repeat checked/unchecked");
				if (arg0.getStateChange() == ItemEvent.DESELECTED) {
					enablePanel(false, repeatPanel);
				}else{
					enablePanel(true, repeatPanel);
					if(rbNever.isSelected()){
						tfDateUntil.setEnabled(false);
					}
				}
		    }else if(source==chbReminder){
		    	//System.out.println("Reminder checked/unchecked");
		    	if (arg0.getStateChange() == ItemEvent.DESELECTED) {
		    		enablePanel(false, reminderPanel);
		    		enablePanel(false, reminderItemsPanel);
				}else{
					enablePanel(true, reminderPanel);
					enablePanel(true, reminderItemsPanel);
				}
		    }else if(source==chbAllDayAppointment){
		    	//System.out.println("All day appointment checked/unchecked");
		    	if(arg0.getStateChange() == ItemEvent.DESELECTED){
		    		cbTimeStart.setEnabled(true);
		    		cbTimeEnd.setEnabled(true);
		    	}else{
		    		cbTimeStart.setEnabled(false);
		    		cbTimeEnd.setEnabled(false);
		    	}
		    }
		}
	}

	public Day getDay() {
		return day;
	}

	public void setDay(Day day) {
		this.day = day;
	}

	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}

	/**
	 * @param old_appointment the old_appointment to set
	 */
	public void setOldAppointment(Appointment old_appointment) {
		this.old_appointment = old_appointment;
	}

	/**
	 * @return the old_appointment
	 */
	public Appointment getOldAppointment() {
		return old_appointment;
	}

}

